package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.constant.RedisConstants;
import com.tianji.learning.domain.po.PointsRecord;
import com.tianji.learning.domain.vo.PointsStatisticsVO;
import com.tianji.learning.enums.PointsRecordType;
import com.tianji.learning.mapper.PointsRecordMapper;
import com.tianji.learning.service.PointsRecordService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author Cammy
 * @description 针对表【points_record(学习积分记录，每个月底清零)】的数据库操作Service实现
 * @createDate 2025-02-24 03:58:44
 */
@Service
@RequiredArgsConstructor
public class PointsRecordServiceImpl extends ServiceImpl<PointsRecordMapper, PointsRecord>
        implements PointsRecordService {

    private final StringRedisTemplate redisTemplate;

    /**
     * todo:保存积分明细
     * @param userId
     * @param points
     * @param type
     */
    @Override
    public void addPointsRecord(Long userId, int points, PointsRecordType type) {
        /*
            ● 写评价 积分+10
            ● 写问答 积分+5 每日获得上限为20分
            ● 写笔记 积分+3 每次被采集+2 每日获得上限为20分
         */
        /*
            开始 --> 是否有积分上限 -是-> 查询今日已得积分是否上限 -是-> 结束
                         |                       |
                     保存积分记录 <————————————————
         */
        LocalDateTime now = LocalDateTime.now();
        int maxPoints = type.getMaxPoints();
        // 1.判断当前方式有没有积分上限
        int realPoints = points;
        if (maxPoints > 0) {
            // 2.有积分上限，需要判断是否超过积分上限
            LocalDateTime begin = DateUtils.getDayStartTime(now);
            LocalDateTime end = DateUtils.getDayEndTime(now);
            // 2.1 查询今日已得积分
            int currentPoints = queryUserPointsByTypeAndDate(userId, type, begin, end);
            // 2.2 判断是否超过上限
            if (currentPoints >= maxPoints) {
                // 2.3 超过，直接结束
                return;
            }
            // 2.4 没超过，但是本次得分和今日得分相加比上限得分高，记录本次的分数
            if (currentPoints + points > maxPoints) {
                realPoints = maxPoints - currentPoints;
            }
        }
        // 3.没有上限，直接保存积分记录
        PointsRecord pointsRecord = new PointsRecord();
        pointsRecord.setPoints(realPoints);
        pointsRecord.setType(type);
        pointsRecord.setUserId(userId);
        this.save(pointsRecord);
        // 4.更新总积分到Redis
        String key = RedisConstants.POINTS_BOARD_KEY_PREFIX + now.format(DateUtils.POINTS_BOARD_SUFFIX_FORMATTER);
        redisTemplate.opsForZSet().incrementScore(key, userId.toString(), realPoints);
    }

    /**
     * 查询我的今日积分
     * @return
     */
    @Override
    public List<PointsStatisticsVO> queryMyPointsToday() {
        // 1.获取当前用户
        Long userId = UserContext.getUser();
        // 2.获取日期
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime begin = DateUtils.getDayStartTime(now);
        LocalDateTime end = DateUtils.getDayEndTime(now);
        // 3.构建查询条件
        LambdaQueryWrapper<PointsRecord> queryWrapper = new LambdaQueryWrapper<PointsRecord>()
                .eq(PointsRecord::getUserId, userId)
                .between(PointsRecord::getCreateTime, begin, end);
        // 4.查询
        List<PointsRecord> list = this.getBaseMapper().queryUserPointsByDate(queryWrapper);
        if (CollUtils.isEmpty(list)) {
            return CollUtils.emptyList();
        }
        // 5.封装返回结果
        List<PointsStatisticsVO> pointsStatisticsVOS = new ArrayList<>(list.size());
        for (PointsRecord pointsRecord : list) {
            PointsStatisticsVO pointsStatisticsVO = new PointsStatisticsVO();
            pointsStatisticsVO.setType(pointsRecord.getType().getDesc());
            pointsStatisticsVO.setMaxPoints(pointsRecord.getType().getMaxPoints());
            pointsStatisticsVO.setPoints(pointsRecord.getPoints());
            pointsStatisticsVOS.add(pointsStatisticsVO);
        }
        return pointsStatisticsVOS;
    }

    private int queryUserPointsByTypeAndDate(Long userId, PointsRecordType type, LocalDateTime begin, LocalDateTime end) {
        // 1.查询条件
        LambdaQueryWrapper<PointsRecord> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .eq(PointsRecord::getUserId, userId)
                .eq(ObjectUtils.isNotEmpty(type), PointsRecord::getType, type)
                .between(ObjectUtils.isAllNotEmpty(begin, end), PointsRecord::getCreateTime, begin, end);
        // 2.调用mapper，查询结果
        Integer points = this.getBaseMapper().queryUserPointsByTypeAndDate(lambdaQueryWrapper);
        // 3.判断并返回
        return points == null ? 0 : points;
    }
}




